home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_325 / keymacro / keymacro.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  14KB  |  755 lines

  1. #include <libraries/arpbase.h>
  2. #include <arpfunctions.h>
  3. #include <stdio.h>
  4. #include <ctype.h>
  5.  
  6. #include "KeyMacro.h"
  7.  
  8. char *CLI_Template    = "STARTUP/K,QUIT/S,INFO/S";
  9. char *CLI_Help        = "\nUsage: \33[1mKeyMacro\33[0m [STARTUP <File>] [QUIT] [INFO]\n";
  10.  
  11. #define ARG_STARTUP    1
  12. #define ARG_QUIT    2
  13. #define ARG_INFO    3
  14. #define ARG_UPDATE    4
  15.  
  16. #define From_CLI    (ThatsMe -> pr_CLI)
  17.  
  18. struct MXMBase    *MXMBase;
  19. struct MSeg    *MSeg;
  20. struct MacroKey    *KeyList;
  21.  
  22. struct KeyAlias KeyTab[22] =
  23. {
  24.     {"TAB",        0x42},
  25.     {"ESC",        0x45},
  26.     {"SPACE",    0x40},
  27.     {"RETURN",    0x44},
  28.     {"ENTER",    0x43},
  29.     {"DEL",        0x46},
  30.     {"BACKSPACE",    0x41},
  31.     {"HELP",    0x5F},
  32.     {"LEFT",    0x4F},
  33.     {"RIGHT",    0x4E},
  34.     {"UP",        0x4C},
  35.     {"DOWN",    0x4D},
  36.  
  37.     {"F1",        0x50},
  38.     {"F2",        0x51},
  39.     {"F3",        0x52},
  40.     {"F4",        0x53},
  41.     {"F5",        0x54},
  42.     {"F6",        0x55},
  43.     {"F7",        0x56},
  44.     {"F8",        0x57},
  45.     {"F9",        0x58},
  46.     {"F10",        0x59}
  47. };
  48.  
  49. struct KeyAlias QualifierTab[9] =
  50. {
  51.     {"NONE",    0},
  52.     {"CTRL",    IEQUALIFIER_CONTROL},
  53.     {"NUMPAD",    IEQUALIFIER_NUMERICPAD},
  54.     {"LSHIFT",    IEQUALIFIER_LSHIFT},
  55.     {"RSHIFT",    IEQUALIFIER_RSHIFT},
  56.     {"LALT",    IEQUALIFIER_LALT},
  57.     {"RALT",    IEQUALIFIER_RALT},
  58.     {"LAMIGA",    IEQUALIFIER_LCOMMAND},
  59.     {"RAMIGA",    IEQUALIFIER_RCOMMAND}
  60. };
  61.  
  62. #asm
  63. _LVORawDoFmt    EQU    $FFFFFDF6
  64.  
  65. StuffChar:    MOVE.B    D0,(A3)+
  66.         RTS
  67.  
  68.         XDEF    _Format
  69.  
  70. _Format:    MOVE.L     4(SP),D1
  71.         MOVE.L     8(SP),D0
  72.         LEA    12(SP),A1
  73.  
  74.         MOVEM.L    A0-A3,-(SP)
  75.  
  76.         MOVE.L    D1,A3
  77.         MOVE.L    D0,A0
  78.         LEA    StuffChar(PC),A2
  79.         MOVE.L    4,A6
  80.         JSR    _LVORawDoFmt(A6)
  81.  
  82.         MOVEM.L    (SP)+,A0-A3
  83.         CLR.L    D0
  84.  
  85.         RTS
  86. #endasm
  87.  
  88. void *
  89. SendCustomMsg(scm_Msg)
  90. struct MacroMessage *scm_Msg;
  91. {
  92.     struct MacroMessage *scm_TempMsg = (struct MacroMessage *)AllocRem(sizeof(struct MacroMessage),MEMF_PUBLIC | MEMF_CLEAR);
  93.  
  94.     if(scm_TempMsg)
  95.     {
  96.         CopyMem(scm_Msg,scm_TempMsg,sizeof(struct MacroMessage));
  97.  
  98.         scm_TempMsg -> mm_Message . mn_Node . ln_Name    = (char *)scm_TempMsg;
  99.         scm_TempMsg -> mm_Message . mn_ReplyPort    = NULL;
  100.         scm_TempMsg -> mm_Message . mn_Length        = sizeof(struct MacroMessage);
  101.  
  102.         PutMsg(&MSeg -> Port,scm_TempMsg);
  103.     }
  104.  
  105.     return((void *)scm_TempMsg);
  106. }
  107.  
  108. UBYTE *
  109. GetToken(s,start)
  110. UBYTE *s;
  111. long *start;
  112. {
  113.     static UBYTE buffer[256];
  114.     long i,j,end = 0,quote = FALSE,maxlen = strlen(s);
  115.     char t;
  116.  
  117.     if(maxlen > 255)
  118.         maxlen = 255;
  119.  
  120.     if(*start > strlen(s) - 1 || !strlen(s) || !s)
  121.         return(NULL);
  122.  
  123.     for(i = *start ; i <= maxlen ; i++)
  124.     {
  125.         if(!end && (s[i] == ' ' || s[i] == '\t'))
  126.         {
  127.             while((s[i] == ' ' || s[i] == '\t') && i < maxlen)
  128.             {
  129.                 i++;
  130.                 (*start)++;
  131.             }
  132.         }
  133.  
  134.         t = s[i];
  135.  
  136.         if(!end && t == '+')
  137.         {
  138.             (*start)++;
  139.             continue;
  140.         }
  141.  
  142.         if(!end && t == '=')
  143.         {
  144.             strcpy(buffer,"=");
  145.             (*start)++;
  146.  
  147.             return(buffer);
  148.         }
  149.  
  150.         if(s[i] == '\\' && s[i + 1] == '\"')
  151.         {
  152.             i += 2;
  153.  
  154.             end = i - *start + 1;
  155.  
  156.             t = s[i];
  157.         }
  158.  
  159.         if(t == '\"' && !quote)
  160.         {
  161.             quote = TRUE;
  162.  
  163.             (*start)++;
  164.  
  165.             end++;
  166.  
  167.             continue;
  168.         }
  169.  
  170.         if((t == '+' || t == '=' || t == ' ' || t == '\t' || t == ';') && quote)
  171.         {
  172.             end++;
  173.             continue;
  174.         }
  175.  
  176.         if((t == '+' || t == '\n' || t == '=' || t == ' ' || t == 0) || (t == '\"' && quote) || (t == ';' && !quote))
  177.         {
  178.             if(t == ';' && !end)
  179.                 return(NULL);
  180.  
  181.             if(t == '\"')
  182.             {
  183.                 strncpy(buffer,s + *start,end - 1);
  184.                 buffer[end - 1] = 0;
  185.             }
  186.             else
  187.             {
  188.                 strncpy(buffer,s + *start,end);
  189.                 buffer[end] = 0;
  190.             }
  191.  
  192.             (*start) += end;
  193.  
  194.             return(buffer);
  195.         }
  196.  
  197.         end++;
  198.     }
  199.  
  200.     return(NULL);
  201. }
  202.  
  203. struct MacroKey *
  204. AddMacroKey(MacroKey)
  205. struct MacroKey *MacroKey;
  206. {
  207.     struct MacroKey *TheKey = NULL;
  208.     long i;
  209.  
  210.     for(i = 0 ; i < MSeg -> NumMacros ; i++)
  211.     {
  212.         if(KeyList[i] . mk_Type == MK_UNUSED)
  213.         {
  214.             TheKey = &KeyList[i];
  215.             break;
  216.         }
  217.     }
  218.  
  219.     if(!TheKey)
  220.         return(NULL);
  221.  
  222.     CopyMem(MacroKey,TheKey,sizeof(struct MacroKey));
  223.  
  224.     return(TheKey);
  225. }
  226.  
  227. BOOL
  228. Interprete(String,Line)
  229. UBYTE *String;
  230. long Line;
  231. {
  232.     ULONG Qualifier = 0;
  233.     ULONG Code = -1;
  234.     struct InputEvent FakeEvent;
  235.     struct MacroKey NewKey;
  236.  
  237.     long Start = 0,Key = FALSE,QuitLoop = FALSE,i,KeyCount = 0;
  238.     UBYTE *Token,*CommandString,*WindowName = NULL,Recognized = FALSE;
  239.  
  240.     UBYTE MessBuff[256],KeyBuff1[40],KeyBuff2[40];
  241.  
  242.     if(String[strlen(String) - 1] == '\n')
  243.         String[strlen(String) - 1] = 0;
  244.  
  245.     if(Token = GetToken(String,&Start))
  246.     {
  247.         if(!UStrCmp("KEY",Token))
  248.             Key = TRUE;
  249.  
  250.         if(UStrCmp("COMMAND",Token) && !Key)
  251.         {
  252.             Format(MessBuff,"Line %ld: Unknown keyword:\n\n'%s'",Line,String);
  253.  
  254.             PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  255.             return(FALSE);
  256.         }
  257.     }
  258.     else
  259.         return(TRUE);
  260.  
  261.     FOREVER
  262.     {
  263.         if(Token = GetToken(String,&Start))
  264.         {
  265.             QuitLoop = TRUE;
  266.  
  267.             for(i = 0 ; i < 9 ; i++)
  268.             {
  269.                 if(!UStrCmp(QualifierTab[i] . ka_Name,Token))
  270.                 {
  271.                     Recognized = TRUE;
  272.                     QuitLoop = FALSE;
  273.  
  274.                     Qualifier |= QualifierTab[i] . ka_Key;
  275.                 }
  276.             }
  277.         }
  278.         else
  279.             break;
  280.  
  281.         if(QuitLoop)
  282.             break;
  283.     }
  284.  
  285.     if(!Recognized)
  286.     {
  287.         Format(MessBuff,"Line %ld: Didn't recognize qualifier:\n\n'%s'",Line,String);
  288.  
  289.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  290.         return(FALSE);
  291.     }
  292.  
  293.     if(Token)
  294.         goto JumpIn;
  295.  
  296.     if(Token = GetToken(String,&Start))
  297.     {
  298. JumpIn:        for(i = 0 ; i < 22 ; i++)
  299.         {
  300.             if(!UStrCmp(KeyTab[i] . ka_Name,Token))
  301.             {
  302.                 Code = KeyTab[i] . ka_Key;
  303.                 goto Next;
  304.             }
  305.         }
  306.  
  307.         if(InvertKey(Token[0],&FakeEvent,IK_USEIKM,NULL))
  308.             Code = FakeEvent . ie_Code;
  309.     }
  310.  
  311.     if(Code == -1)
  312.     {
  313.         Format(MessBuff,"Line %ld: Didn't recognize key:\n\n'%s'",Line,String);
  314.  
  315.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  316.         return(FALSE);
  317.     }
  318.  
  319. Next:    FOREVER
  320.     {
  321.         if(Token = GetToken(String,&Start))
  322.         {
  323.             if(!UStrCmp("=",Token))
  324.                 break;
  325.         }
  326.         else
  327.         {
  328.             Format(MessBuff,"Line %ld: Statement '=' missing:\n\n'%s'",Line,String);
  329.  
  330.             PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  331.             return(FALSE);
  332.         }
  333.     }
  334.  
  335.     if(Token = GetToken(String,&Start))
  336.         strcpy(KeyBuff1,Token);
  337.     else
  338.     {
  339.         Format(MessBuff,"Line %ld: Didn't find macro:\n\n'%s'",Line,String);
  340.  
  341.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  342.         return(FALSE);
  343.     }
  344.  
  345.     if(Key)
  346.         goto AddIt;
  347.  
  348.     if(!(Token = GetToken(String,&Start)))
  349.         goto AddIt;
  350.  
  351.     if(UStrCmp("WINDOW",Token))
  352.     {
  353.         Format(MessBuff,"Line %ld: Didn't recognize 'WINDOW' statement:\n\n'%s'",Line,String);
  354.  
  355.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  356.         return(FALSE);
  357.     }
  358.  
  359.     if(!(Token = GetToken(String,&Start)))
  360.     {
  361.         Format(MessBuff,"Line %ld: Didn't find window title:\n\n'%s'",Line,String);
  362.  
  363.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  364.         return(FALSE);
  365.     }
  366.  
  367.     if(!(WindowName = (UBYTE *)AllocRem(strlen(Token) + 1,MEMF_PUBLIC)))
  368.     {
  369.         PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE,NULL);
  370.         return(FALSE);
  371.     }
  372.  
  373.     strcpy(WindowName,Token);
  374.  
  375. AddIt:    for(i = 0 ; i < strlen(KeyBuff1) ; i++)
  376.     {
  377.         UBYTE c;
  378.  
  379.         if(KeyBuff1[i] != '\\')
  380.         {
  381.             KeyBuff2[KeyCount++] = KeyBuff1[i];
  382.             continue;
  383.         }
  384.  
  385.         if(i == strlen(KeyBuff1) - 1)
  386.             break;
  387.  
  388.         i++;
  389.  
  390.         c = 0;
  391.  
  392.         switch(ToUpper(KeyBuff1[i]))
  393.         {
  394.             case 'U':    c = KC_CURSORUP;
  395.                     break;
  396.  
  397.             case 'D':    c = KC_CURSORDOWN;
  398.                     break;
  399.  
  400.             case 'L':    c = KC_CURSORLEFT;
  401.                     break;
  402.  
  403.             case 'R':    c = KC_CURSORRIGHT;
  404.                     break;
  405.  
  406.             case 'H':    c = KC_HELP;
  407.                     break;
  408.  
  409.             case 'B':    c = 8;
  410.                     break;
  411.  
  412.             case 'E':    c = 127;
  413.                     break;
  414.  
  415.             case 'F':    if(i == strlen(KeyBuff1) - 1)
  416.                         break;
  417.  
  418.                     i++;
  419.  
  420.                     if(!isdigit(KeyBuff1[i]))
  421.                         break;
  422.  
  423.                     if(!KeyBuff1[i] == '1')
  424.                     {
  425.                         c = KC_FKEY1 + KeyBuff1[i] - '1';
  426.                         break;
  427.                     }
  428.  
  429.                     if(i == strlen(KeyBuff1) - 1)
  430.                         break;
  431.  
  432.                     i++;
  433.  
  434.                     if(!isdigit(KeyBuff1[i]))
  435.                     {
  436.                         c = KC_FKEY1;
  437.                         break;
  438.                     }
  439.  
  440.                     if(KeyBuff1[i] != '0')
  441.                         break;
  442.  
  443.                     c = KC_FKEY10;
  444.                     break;
  445.  
  446.             case 'N':    c = '\n';
  447.                     break;
  448.  
  449.             case '\\':    c = '\\';
  450.                     break;
  451.  
  452.             default:    c = KeyBuff1[i];
  453.  
  454.                     break;
  455.         }
  456.  
  457.         if(c)
  458.             KeyBuff2[KeyCount++] = c;
  459.     }
  460.  
  461.     KeyBuff2[KeyCount] = 0;
  462.  
  463.     if(!(CommandString = (UBYTE *)AllocRem(strlen(KeyBuff2) + 1,MEMF_PUBLIC)))
  464.     {
  465.         PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE,NULL);
  466.         FreeRem(WindowName);
  467.  
  468.         return(FALSE);
  469.     }
  470.  
  471.     strcpy(CommandString,KeyBuff2);
  472.  
  473.     setmem(&NewKey,sizeof(struct MacroKey),0);
  474.  
  475.     NewKey . mk_CommandKey        = Code;
  476.     NewKey . mk_CommandQualifier    = Qualifier;
  477.  
  478.     NewKey . mk_String        = CommandString;
  479.     NewKey . mk_Window        = WindowName;
  480.  
  481.     if(Key)
  482.         NewKey . mk_Type    = MK_WORD;
  483.     else
  484.         NewKey . mk_Type    = MK_COMMAND;
  485.  
  486.     if(AddMacroKey(&NewKey))
  487.         return(TRUE);
  488.  
  489.     Format(MessBuff,"Line %ld: Key macro table full.",Line);
  490.  
  491.     PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  492.     return(FALSE);
  493. }
  494.  
  495. BOOL
  496. UpdateList(Name)
  497. char *Name;
  498. {
  499.     char LineBuff[256];
  500.     long LineNum = 1;
  501.     FILE *ConfigFile;
  502.  
  503.     if(!Name)
  504.         Name = "S:KeyMacro.config";
  505.  
  506.     if(!(KeyList = (struct MacroKey *)AllocRem(sizeof(struct MacroKey) * MAXMACROS,MEMF_PUBLIC | MEMF_CLEAR)))
  507.     {
  508.         PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE,NULL);
  509.         return(FALSE);
  510.     }
  511.  
  512.     MSeg -> NumMacros = MAXMACROS;
  513.  
  514.     if(ConfigFile = fopen(Name,"r"))
  515.     {
  516.         while(fgets(LineBuff,256,ConfigFile))
  517.         {
  518.             if(!Interprete(LineBuff,LineNum++))
  519.             {
  520.                 fclose(ConfigFile);
  521.  
  522.                 FreeRem(KeyList);
  523.  
  524.                 return(FALSE);
  525.             }
  526.         }
  527.  
  528.         fclose(ConfigFile);
  529.     }
  530.     else
  531.     {
  532.         PopRequest(NULL,"KeyMacro Problem:","Couldn't open configuration file!",NULL,"Continue?",FALSE,NULL);
  533.         return(FALSE);
  534.     }
  535.  
  536.     return(TRUE);
  537. }
  538.  
  539. Chk_Abort() { return(0); }
  540.  
  541. void
  542. main(argc,argv)
  543. long argc;
  544. char *argv[];
  545. {
  546.     struct Process *ThatsMe = (struct Process *)FindTask(NULL);
  547.     BOOL Created = FALSE;
  548.     char *FileName = argv[ARG_STARTUP];
  549.     long i;
  550.  
  551.     if(!From_CLI)
  552.         FileName = NULL;
  553.  
  554.     if(!(MXMBase = (struct MXMBase *)OpenLibrary("mxm.library",0)))
  555.     {
  556.         if(From_CLI)
  557.             Puts("\33[1mKeyMacro:\33[0m You need the \33[1mmxm.library\33[0m to run this program.");
  558.  
  559.         exit(5);
  560.     }
  561.  
  562.     MSeg = (struct MSeg *)FindPort(PORTNAME);
  563.  
  564.     if(argv[ARG_INFO])
  565.     {
  566.         Printf("\n\33[1m\33[33mKeyMacro\33[31m\33[0m the Amiga macro key handler.\n\n");
  567.  
  568.         Printf("         This program may be non-commercially\n");
  569.         Printf("         re-distributed!\n\n");
  570.  
  571.         Printf("\33[1m\33[33mAuthor\33[31m\33[0m - Olaf Barthel of MXM\n");
  572.         Printf("         Brabeckstrasse 35\n");
  573.         Printf("         D-3000 Hannover 71\n\n");
  574.  
  575.         Printf("     Federal Republic of Germany.\n\n");
  576.  
  577.         CloseLibrary(MXMBase);
  578.  
  579.         exit(0);
  580.     }
  581.  
  582.     if(argv[ARG_QUIT])
  583.     {
  584.         Printf("Removing \33[1m\33[33mKeyMacro\33[31m\33[0m, ");
  585.  
  586.         if(!MSeg)
  587.         {
  588.             Printf("failed!\7\n");
  589.  
  590.             CloseLibrary(MXMBase);
  591.  
  592.             exit(0);
  593.         }
  594.  
  595.         MSeg -> Father = (struct Task *)FindTask(NULL);
  596.  
  597.         if(MSeg -> Child)
  598.         {
  599.             Signal(MSeg -> Child,SIG_CLOSE);
  600.             Wait(SIG_CLOSE);
  601.         }
  602.  
  603.         RemPort(&MSeg -> Port);
  604.         FreeRem(MSeg -> Port . mp_Node . ln_Name);
  605.  
  606.         if(MSeg -> Segment)
  607.             UnLoadSeg(MSeg -> Segment);
  608.  
  609.         if(MSeg -> MacroList)
  610.         {
  611.             for(i = 0 ; i < MSeg -> NumMacros ; i++)
  612.             {
  613.                 if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  614.                     continue;
  615.  
  616.                 if(MSeg -> MacroList[i] . mk_String)
  617.                     FreeRem(MSeg -> MacroList[i] . mk_String);
  618.  
  619.                 if(MSeg -> MacroList[i] . mk_Window)
  620.                     FreeRem(MSeg -> MacroList[i] . mk_Window);
  621.             }
  622.  
  623.             FreeRem(MSeg -> MacroList);
  624.         }
  625.  
  626.         FreeRem(MSeg);
  627.  
  628.         Printf("OK.\n");
  629.  
  630.         CloseLibrary(MXMBase);
  631.  
  632.         exit(0);
  633.     }
  634.  
  635.     if(!MSeg)
  636.     {
  637.         if(MSeg = (struct MSeg *)AllocRem(sizeof(struct MSeg),MEMF_PUBLIC | MEMF_CLEAR))
  638.         {
  639.             MSeg -> Port . mp_Flags        = PA_IGNORE;
  640.             MSeg -> Port . mp_Node . ln_Pri    = 0;
  641.             MSeg -> Port . mp_Node . ln_Type= NT_MSGPORT;
  642.             MSeg -> Port . mp_Node . ln_Name= AllocRem(sizeof(PORTNAME),MEMF_PUBLIC);
  643.             MSeg -> Child            = NULL;
  644.             MSeg -> Father            = (struct Task *)FindTask(NULL);
  645.             MSeg -> SegSize            = sizeof(struct MSeg);
  646.             MSeg -> RingBack        = SIGBREAKF_CTRL_C;
  647.             MSeg -> Revision        = REVISION;
  648.  
  649.             NewList(&MSeg -> Port . mp_MsgList);
  650.  
  651.             if(From_CLI)
  652.             {
  653.                 Printf("\33[1m\33[33mKeyMacro v1.%ld \33[31m\33[0m(C) Copyright 1989, 1990 by \33[4mMXM\33[0m.\n",REVISION);
  654.  
  655.                 Printf("Installing \33[33m\33[1mKeyMacro\33[0m\33[31m, ");
  656.             }
  657.  
  658.             if(MSeg -> Port . mp_Node . ln_Name)
  659.                 strcpy(MSeg -> Port . mp_Node . ln_Name,PORTNAME);
  660.             else
  661.             {
  662.                 if(From_CLI)
  663.                     Printf("failed!\n");
  664.  
  665.                 CloseLibrary(MXMBase);
  666.  
  667.                 exit(20);
  668.             }
  669.  
  670.             MSeg -> Segment = (BPTR)LoadSeg("KeyMacro-Handler");
  671.  
  672.             if(!MSeg -> Segment)
  673.                 MSeg -> Segment = (BPTR)LoadSeg("L:KeyMacro-Handler");
  674.  
  675.             if(!MSeg -> Segment)
  676.             {
  677.                 if(From_CLI)
  678.                     Printf("unable to find \33[33mL:KeyMacro-Handler\33[31m\7!\n");
  679.  
  680.                 FreeRem(MSeg -> Port . mp_Node . ln_Name);
  681.                 FreeRem(MSeg);
  682.             }
  683.             else
  684.             {
  685.                 AddPort(&MSeg -> Port);
  686.  
  687.                 CreateProc("KeyMacro-Handler",10,MSeg -> Segment,4096);
  688.  
  689.                 Wait(SIGBREAKF_CTRL_C);
  690.  
  691.                 if(!MSeg -> Child)
  692.                 {
  693.                     if(From_CLI)
  694.                         Printf("\33[33mFAILED!\33[31m (care to retry?)\n");
  695.  
  696.                     RemPort(&MSeg -> Port);
  697.                     FreeRem(MSeg -> Port . mp_Node . ln_Name);
  698.  
  699.                     if(MSeg -> Segment)
  700.                         UnLoadSeg(MSeg -> Segment);
  701.  
  702.                     FreeRem(MSeg);
  703.  
  704.                     CloseLibrary(MXMBase);
  705.  
  706.                     exit(20);
  707.                 }
  708.                 else
  709.                 {
  710.                     if(From_CLI)
  711.                         Printf("initializing, ");
  712.  
  713.                     InvertKey(NULL,NULL,IK_USEIKM | IK_BUILDLIST,NULL);
  714.  
  715.                     if(From_CLI)
  716.                         Puts("Okay.");
  717.                     else
  718.                         PopRequest(NULL,"KeyMacro Info:","\33[1mKeyMacro\33[0m installed.",NULL,"Continue?",FALSE,NULL);
  719.  
  720.                     Created = TRUE;
  721.                 }
  722.             }
  723.         }
  724.     }
  725.  
  726.     if(UpdateList(FileName))
  727.     {
  728.         if(Created)
  729.         {
  730.             MSeg -> NumMacros = MAXMACROS;
  731.             MSeg -> MacroList = KeyList;
  732.         }
  733.         else
  734.         {
  735.             struct MacroMessage UpdateMsg;
  736.  
  737.             UpdateMsg . mm_Type    = MM_UPDATE;
  738.             UpdateMsg . mm_NumMacros= MAXMACROS;
  739.             UpdateMsg . mm_MacroList= KeyList;
  740.  
  741.             SendCustomMsg(&UpdateMsg);
  742.  
  743.             if(From_CLI)
  744.                 Printf("\33[1mKeyMacro:\33[0m Updating macro keys...\n");
  745.         }
  746.     }
  747.     else
  748.     {
  749.         CloseLibrary(MXMBase);
  750.         exit(10);
  751.     }
  752.  
  753.     CloseLibrary(MXMBase);
  754. }
  755.